//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: urlprov.cpp // // Contents: CryptGetObjectUrl provider implementation // // History: 16-Sep-97 kirtd Created // //---------------------------------------------------------------------------- #include //+--------------------------------------------------------------------------- // // Function: CertificateIssuerGetObjectUrl // // Synopsis: get certificate issuer URL // //---------------------------------------------------------------------------- BOOL WINAPI CertificateIssuerGetObjectUrl ( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN OPTIONAL LPVOID pvReserved ) { return( ObjectContextUrlFromInfoAccess( CONTEXT_OID_CERTIFICATE, pvPara, (DWORD) -1L, szOID_AUTHORITY_INFO_ACCESS, dwFlags, szOID_PKIX_CA_ISSUERS, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CertificateCrlDistPointGetObjectUrl // // Synopsis: get certificate CRL URL // //---------------------------------------------------------------------------- BOOL WINAPI CertificateCrlDistPointGetObjectUrl ( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { return( ObjectContextUrlFromCrlDistPoint( CONTEXT_OID_CERTIFICATE, pvPara, (DWORD) -1L, dwFlags, szOID_CRL_DIST_POINTS, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CertificateFreshestCrlGetObjectUrl // // Synopsis: get certificate freshest CRL URL // //---------------------------------------------------------------------------- BOOL WINAPI CertificateFreshestCrlGetObjectUrl( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN OPTIONAL LPVOID pvReserved ) { return( ObjectContextUrlFromCrlDistPoint( CONTEXT_OID_CERTIFICATE, pvPara, (DWORD) -1L, dwFlags, szOID_FRESHEST_CRL, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CrlFreshestCrlGetObjectUrl // // Synopsis: get freshest CRL URL from the certificate's base CRL // //---------------------------------------------------------------------------- BOOL WINAPI CrlFreshestCrlGetObjectUrl( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN OPTIONAL LPVOID pvReserved ) { PCCERT_CRL_CONTEXT_PAIR pCertCrlPair = (PCCERT_CRL_CONTEXT_PAIR) pvPara; return( ObjectContextUrlFromCrlDistPoint( CONTEXT_OID_CRL, (LPVOID) pCertCrlPair->pCrlContext, (DWORD) -1L, dwFlags, szOID_FRESHEST_CRL, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CtlIssuerGetObjectUrl // // Synopsis: get CTL issuer URL // //---------------------------------------------------------------------------- BOOL WINAPI CtlIssuerGetObjectUrl ( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { PURL_OID_CTL_ISSUER_PARAM pParam = (PURL_OID_CTL_ISSUER_PARAM)pvPara; return( ObjectContextUrlFromInfoAccess( CONTEXT_OID_CTL, (LPVOID)pParam->pCtlContext, pParam->SignerIndex, szOID_AUTHORITY_INFO_ACCESS, CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE | CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE, szOID_PKIX_CA_ISSUERS, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CtlNextUpdateGetObjectUrl // // Synopsis: get CTL renewal URL // //---------------------------------------------------------------------------- BOOL WINAPI CtlNextUpdateGetObjectUrl ( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { LPVOID* apv = (LPVOID *)pvPara; return( ObjectContextUrlFromNextUpdateLocation( CONTEXT_OID_CTL, apv[0], (DWORD)(DWORD_PTR)apv[1], dwFlags, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: CrlIssuerGetObjectUrl // // Synopsis: get CRL issuer URL // //---------------------------------------------------------------------------- BOOL WINAPI CrlIssuerGetObjectUrl ( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { return( ObjectContextUrlFromInfoAccess( CONTEXT_OID_CRL, pvPara, (DWORD) -1L, szOID_AUTHORITY_INFO_ACCESS, dwFlags, szOID_PKIX_CA_ISSUERS, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved ) ); } //+--------------------------------------------------------------------------- // // Function: ObjectContextUrlFromInfoAccess // // Synopsis: get the URLs specified by the access method OID from the given // context and format it as a CRYPT_URL_ARRAY // //---------------------------------------------------------------------------- BOOL WINAPI ObjectContextUrlFromInfoAccess ( IN LPCSTR pszContextOid, IN LPVOID pvContext, IN DWORD Index, IN LPCSTR pszInfoAccessOid, IN DWORD dwFlags, IN LPCSTR pszAccessMethodOid, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { BOOL fResult = FALSE; CRYPT_RAW_URL_DATA RawData[MAX_RAW_URL_DATA]; ULONG cRawData = MAX_RAW_URL_DATA; fResult = ObjectContextGetRawUrlData( pszContextOid, pvContext, Index, dwFlags, pszInfoAccessOid, RawData, &cRawData ); if ( fResult == TRUE ) { fResult = GetUrlArrayAndInfoFromInfoAccess( cRawData, RawData, pszAccessMethodOid, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo ); ObjectContextFreeRawUrlData( cRawData, RawData ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: ObjectContextUrlFromCrlDistPoint // // Synopsis: get the URLs from the CRL distribution point on the object and // format as a CRYPT_URL_ARRAY // //---------------------------------------------------------------------------- BOOL WINAPI ObjectContextUrlFromCrlDistPoint ( IN LPCSTR pszContextOid, IN LPVOID pvContext, IN DWORD Index, IN DWORD dwFlags, IN LPCSTR pszSourceOid, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { BOOL fResult = FALSE; CRYPT_RAW_URL_DATA RawData[MAX_RAW_URL_DATA]; ULONG cRawData = MAX_RAW_URL_DATA; fResult = ObjectContextGetRawUrlData( pszContextOid, pvContext, Index, dwFlags, pszSourceOid, RawData, &cRawData ); if ( fResult == TRUE ) { fResult = GetUrlArrayAndInfoFromCrlDistPoint( cRawData, RawData, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo ); ObjectContextFreeRawUrlData( cRawData, RawData ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: ObjectContextUrlFromNextUpdateLocation // // Synopsis: get the URLs from the next update location // //---------------------------------------------------------------------------- BOOL WINAPI ObjectContextUrlFromNextUpdateLocation ( IN LPCSTR pszContextOid, IN LPVOID pvContext, IN DWORD Index, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { BOOL fResult = FALSE; CRYPT_RAW_URL_DATA RawData[MAX_RAW_URL_DATA]; ULONG cRawData = MAX_RAW_URL_DATA; fResult = ObjectContextGetRawUrlData( pszContextOid, pvContext, Index, dwFlags, szOID_NEXT_UPDATE_LOCATION, RawData, &cRawData ); if ( fResult == TRUE ) { fResult = GetUrlArrayAndInfoFromNextUpdateLocation( cRawData, RawData, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo ); ObjectContextFreeRawUrlData( cRawData, RawData ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: InitializeDefaultUrlInfo // // Synopsis: initialize default URL info // //---------------------------------------------------------------------------- VOID WINAPI InitializeDefaultUrlInfo ( OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT DWORD* pcbUrlInfo ) { if ( pUrlInfo == NULL ) { *pcbUrlInfo = sizeof( CRYPT_URL_INFO ); return; } if (*pcbUrlInfo >= sizeof( CRYPT_URL_INFO )) { *pcbUrlInfo = sizeof( CRYPT_URL_INFO ); memset( pUrlInfo, 0, sizeof( CRYPT_URL_INFO ) ); pUrlInfo->cbSize = sizeof( CRYPT_URL_INFO ); } else if (*pcbUrlInfo >= sizeof( DWORD )) { *pcbUrlInfo = sizeof( DWORD ); pUrlInfo->cbSize = sizeof( DWORD ); } } //+--------------------------------------------------------------------------- // // Function: ObjectContextGetRawUrlData // // Synopsis: Raw URL data is a decoded extension, property or attribute // specified by a source OID that contains locator information. // This API retrieves and decodes such data // //---------------------------------------------------------------------------- BOOL WINAPI ObjectContextGetRawUrlData ( IN LPCSTR pszContextOid, IN LPVOID pvContext, IN DWORD Index, IN DWORD dwFlags, IN LPCSTR pszSourceOid, OUT PCRYPT_RAW_URL_DATA aRawUrlData, IN OUT DWORD* pcRawUrlData ) { BOOL fResult = TRUE; DWORD cCount; DWORD cError = 0; DWORD cRawData = 0; CRYPT_RAW_URL_DATA RawData[MAX_RAW_URL_DATA]; CRYPT_DATA_BLOB DataBlob = {0, NULL}; BOOL fFreeDataBlob = FALSE; DWORD cbDecoded; LPBYTE pbDecoded = NULL; PCRYPT_ATTRIBUTE pAttr = NULL; DWORD cbAttr; if ( dwFlags & CRYPT_GET_URL_FROM_PROPERTY ) { RawData[cRawData].dwFlags = CRYPT_GET_URL_FROM_PROPERTY; RawData[cRawData].pvData = NULL; cRawData += 1; } if ( dwFlags & CRYPT_GET_URL_FROM_EXTENSION ) { RawData[cRawData].dwFlags = CRYPT_GET_URL_FROM_EXTENSION; RawData[cRawData].pvData = NULL; cRawData += 1; } if ( dwFlags & CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE ) { RawData[cRawData].dwFlags = CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE; RawData[cRawData].pvData = NULL; cRawData += 1; } if ( dwFlags & CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE ) { RawData[cRawData].dwFlags = CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE; RawData[cRawData].pvData = NULL; cRawData += 1; } if ( *pcRawUrlData < cRawData ) { SetLastError( (DWORD) E_INVALIDARG ); return( FALSE ); } for ( cCount = 0; cCount < cRawData; cCount++ ) { switch ( RawData[cCount].dwFlags ) { case CRYPT_GET_URL_FROM_PROPERTY: { DWORD PropId; fResult = MapOidToPropertyId( pszSourceOid, &PropId ); if ( fResult == TRUE ) { fResult = ObjectContextGetProperty( pszContextOid, pvContext, PropId, NULL, &DataBlob.cbData ); } if ( fResult == TRUE ) { DataBlob.pbData = new BYTE [ DataBlob.cbData ]; if ( DataBlob.pbData != NULL ) { fFreeDataBlob = TRUE; fResult = ObjectContextGetProperty( pszContextOid, pvContext, PropId, DataBlob.pbData, &DataBlob.cbData ); } else { fResult = FALSE; SetLastError( (DWORD) E_OUTOFMEMORY ); } } } break; case CRYPT_GET_URL_FROM_EXTENSION: { PCERT_EXTENSION pExt; pExt = ObjectContextFindExtension( pszContextOid, pvContext, pszSourceOid ); if ( pExt != NULL ) { DataBlob.cbData = pExt->Value.cbData; DataBlob.pbData = pExt->Value.pbData; fResult = TRUE; } else { fResult = FALSE; } } break; case CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE: case CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE: { fResult = ObjectContextGetAttribute( pszContextOid, pvContext, Index, RawData[cCount].dwFlags, pszSourceOid, NULL, &cbAttr ); if ( fResult == TRUE ) { pAttr = (PCRYPT_ATTRIBUTE)new BYTE [cbAttr]; if ( pAttr != NULL ) { fResult = ObjectContextGetAttribute( pszContextOid, pvContext, Index, RawData[cCount].dwFlags, pszSourceOid, pAttr, &cbAttr ); } else { fResult = FALSE; SetLastError( (DWORD) E_OUTOFMEMORY ); } } if ( fResult == TRUE ) { // We only deal with single valued attributes DataBlob.cbData = pAttr->rgValue[0].cbData; DataBlob.pbData = pAttr->rgValue[0].pbData; } } break; } if ( fResult == TRUE ) { fResult = CryptDecodeObject( X509_ASN_ENCODING, pszSourceOid, DataBlob.pbData, DataBlob.cbData, 0, NULL, &cbDecoded ); if ( fResult == TRUE ) { pbDecoded = new BYTE [ cbDecoded ]; if ( pbDecoded != NULL ) { fResult = CryptDecodeObject( X509_ASN_ENCODING, pszSourceOid, DataBlob.pbData, DataBlob.cbData, 0, pbDecoded, &cbDecoded ); } else { fResult = FALSE; } } } if ( fResult == TRUE ) { RawData[cCount].pvData = (LPVOID)pbDecoded; } else { if ( pbDecoded != NULL ) { delete [] pbDecoded; } cError += 1; } pbDecoded = NULL; if ( fFreeDataBlob == TRUE ) { delete [] DataBlob.pbData; fFreeDataBlob = FALSE; } if ( pAttr != NULL ) { delete [] (BYTE *)pAttr; pAttr = NULL; } } if ( cError != cRawData ) { memcpy( aRawUrlData, RawData, cRawData * sizeof( CRYPT_RAW_URL_DATA ) ); *pcRawUrlData = cRawData; fResult = TRUE; } else { SetLastError( (DWORD) CRYPT_E_NOT_FOUND ); fResult = FALSE; } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: ObjectContextFreeRawUrlData // // Synopsis: free the raw URL data // //---------------------------------------------------------------------------- VOID WINAPI ObjectContextFreeRawUrlData ( IN DWORD cRawUrlData, IN PCRYPT_RAW_URL_DATA aRawUrlData ) { DWORD cCount; for ( cCount = 0; cCount < cRawUrlData; cCount++ ) { delete [] (BYTE *) aRawUrlData[cCount].pvData; } } //+--------------------------------------------------------------------------- // // Function: GetUrlArrayAndInfoFromAuthInfoAccess // // Synopsis: get URL data using decoded info access data // //---------------------------------------------------------------------------- BOOL WINAPI GetUrlArrayAndInfoFromInfoAccess ( IN DWORD cRawUrlData, IN PCRYPT_RAW_URL_DATA aRawUrlData, IN LPCSTR pszAccessMethodOid, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo ) { BOOL fResult = FALSE; PCERT_AUTHORITY_INFO_ACCESS pAuthInfoAccess = NULL; PCERT_ACCESS_DESCRIPTION rgAccDescr = NULL; DWORD cRaw; DWORD cCount; BOOL fAnyFound = FALSE; CCryptUrlArray cua( 1, 5, fResult ); for ( cRaw = 0; ( fResult == TRUE ) && ( cRaw < cRawUrlData ); cRaw++ ) { pAuthInfoAccess = (PCERT_AUTHORITY_INFO_ACCESS)aRawUrlData[cRaw].pvData; if ( pAuthInfoAccess != NULL ) { rgAccDescr = pAuthInfoAccess->rgAccDescr; for ( cCount = 0; ( cCount < pAuthInfoAccess->cAccDescr ) && ( fResult == TRUE ); cCount++ ) { if ( !strcmp( pszAccessMethodOid, rgAccDescr[cCount].pszAccessMethod ) ) { if ( rgAccDescr[cCount].AccessLocation.dwAltNameChoice == CERT_ALT_NAME_URL ) { fResult = cua.AddUrl( rgAccDescr[cCount].AccessLocation.pwszURL, TRUE ); fAnyFound = TRUE; } } } } } if ( ( fAnyFound == FALSE ) && ( fResult == TRUE ) ) { SetLastError( (DWORD) CRYPT_E_NOT_FOUND ); fResult = FALSE; } if ( fResult == TRUE ) { PCRYPT_URL_ARRAY* ppUrlArray = NULL; if ( pUrlArray != NULL ) { ppUrlArray = &pUrlArray; } fResult = cua.GetArrayInSingleBufferEncodedForm( ppUrlArray, pcbUrlArray ); } if ( ( fResult == TRUE ) && ( pcbUrlInfo != NULL ) ) { InitializeDefaultUrlInfo( pUrlInfo, pcbUrlInfo ); } cua.FreeArray( TRUE ); return( fResult ); } #define DIR_NAME_LDAP_URL_PREFIX L"ldap://" #define URL_OID_CDP_DIR_NAME_LDAP_HOST_PORTS_VALUE_NAME \ L"DirectoryNameLdapHostPorts" #define URL_OID_CDP_DIR_NAME_LDAP_SUFFIX_VALUE_NAME \ L"DirectoryNameLdapSuffix" LPCWSTR pwszDefaultCDPDirNameLdapUrlHostPorts = L"\0\0"; LPCWSTR pwszDefaultCDPDirNameLdapUrlSuffix= L"?certificateRevocationList;binary,authorityRevocationList;binary,deltaRevocationList;binary"; LPWSTR WINAPI GetCDPOIDFunctionValue( IN LPCWSTR pwszValueName ) { BOOL fResult; DWORD dwType; DWORD cchValue; DWORD cbValue = 0; LPWSTR pwszValue = NULL; fResult = CryptGetOIDFunctionValue( X509_ASN_ENCODING, URL_OID_GET_OBJECT_URL_FUNC, URL_OID_CERTIFICATE_CRL_DIST_POINT, pwszValueName, &dwType, NULL, &cbValue ); cchValue = cbValue / sizeof(WCHAR); if (!fResult || 0 == cchValue || !(REG_MULTI_SZ == dwType || REG_SZ == dwType || REG_EXPAND_SZ == dwType)) goto ErrorReturn; pwszValue = new WCHAR [cchValue + 2]; if (NULL == pwszValue) goto OutOfMemory; fResult = CryptGetOIDFunctionValue( X509_ASN_ENCODING, URL_OID_GET_OBJECT_URL_FUNC, URL_OID_CERTIFICATE_CRL_DIST_POINT, pwszValueName, &dwType, (BYTE *) pwszValue, &cbValue ); if (!fResult) goto ErrorReturn; // Ensure the value has two null terminators pwszValue[cchValue] = L'\0'; pwszValue[cchValue + 1] = L'\0'; CommonReturn: return pwszValue; ErrorReturn: if (pwszValue) { delete [] pwszValue; pwszValue = NULL; } goto CommonReturn; OutOfMemory: SetLastError( (DWORD) E_OUTOFMEMORY ); goto ErrorReturn; } // For an error or no found registry value, // returns pwszDefaultCDPDirNameLdapUrlHostPorts LPWSTR WINAPI GetCDPDirNameLdapUrlHostPorts() { LPWSTR pwszHostPorts; pwszHostPorts = GetCDPOIDFunctionValue( URL_OID_CDP_DIR_NAME_LDAP_HOST_PORTS_VALUE_NAME); if (NULL == pwszHostPorts) pwszHostPorts = (LPWSTR) pwszDefaultCDPDirNameLdapUrlHostPorts; return pwszHostPorts; } // For an error or no found registry value, // returns pwszDefaultCDPDirNameLdapUrlSuffix LPWSTR WINAPI GetCDPDirNameLdapUrlSuffix() { LPWSTR pwszSuffix = NULL; pwszSuffix = GetCDPOIDFunctionValue( URL_OID_CDP_DIR_NAME_LDAP_SUFFIX_VALUE_NAME); if (NULL == pwszSuffix) pwszSuffix = (LPWSTR) pwszDefaultCDPDirNameLdapUrlSuffix; return pwszSuffix; } BOOL WINAPI AddUrlsFromCDPDirectoryName ( IN PCERT_NAME_BLOB pDirNameBlob, IN OUT CCryptUrlArray *pcua ) { BOOL fResult; LPWSTR pwszHP; LPWSTR pwszHostPorts; LPWSTR pwszSuffix; LPWSTR pwszDirName = NULL; DWORD cchDirName; pwszHostPorts = GetCDPDirNameLdapUrlHostPorts(); pwszSuffix = GetCDPDirNameLdapUrlSuffix(); assert(NULL != pwszHostPorts && NULL != pwszSuffix); cchDirName = CertNameToStrW( X509_ASN_ENCODING, pDirNameBlob, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, NULL, // pwsz 0 // cch ); if (1 >= cchDirName) goto ErrorReturn; pwszDirName = new WCHAR [cchDirName]; if (NULL == pwszDirName) goto OutOfMemory; cchDirName = CertNameToStrW( X509_ASN_ENCODING, pDirNameBlob, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, pwszDirName, cchDirName ); if (1 >= cchDirName) goto ErrorReturn; cchDirName--; // exclude trailing L'\0' pwszHP = pwszHostPorts; while (TRUE) { DWORD cchHP; LPWSTR pwszUrl; DWORD cchUrl; // Skip past any spaces in the HostPort while (L' ' == *pwszHP) pwszHP++; cchHP = wcslen(pwszHP); cchUrl = wcslen(DIR_NAME_LDAP_URL_PREFIX); cchUrl += cchHP; cchUrl += 1; // L'/' cchUrl += cchDirName; cchUrl += wcslen(pwszSuffix); cchUrl += 1; // L'\0' pwszUrl = new WCHAR [cchUrl]; if (NULL == pwszUrl) goto OutOfMemory; wcscpy(pwszUrl, DIR_NAME_LDAP_URL_PREFIX); wcscat(pwszUrl, pwszHP); wcscat(pwszUrl, L"/"); wcscat(pwszUrl, pwszDirName); wcscat(pwszUrl, pwszSuffix); fResult = pcua->AddUrl(pwszUrl, TRUE); delete [] pwszUrl; if (!fResult) goto ErrorReturn; pwszHP += cchHP + 1; if (L'\0' == *pwszHP) break; } fResult = TRUE; CommonReturn: if (pwszDirName) delete [] pwszDirName; if (pwszHostPorts != pwszDefaultCDPDirNameLdapUrlHostPorts) delete [] pwszHostPorts; if (pwszSuffix != pwszDefaultCDPDirNameLdapUrlSuffix) delete [] pwszSuffix; return fResult; ErrorReturn: fResult = FALSE; goto CommonReturn; OutOfMemory: SetLastError( (DWORD) E_OUTOFMEMORY ); goto ErrorReturn; } //+--------------------------------------------------------------------------- // // Function: GetUrlArrayAndInfoFromCrlDistPoint // // Synopsis: get URL data using decoded CRL distribution point info // //---------------------------------------------------------------------------- BOOL WINAPI GetUrlArrayAndInfoFromCrlDistPoint ( IN DWORD cRawUrlData, IN PCRYPT_RAW_URL_DATA aRawUrlData, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo ) { BOOL fResult = FALSE; PCRL_DIST_POINTS_INFO pDistPointsInfo; PCRL_DIST_POINT rgDistPoint; PCRL_DIST_POINT_NAME pDistPointName; PCERT_ALT_NAME_ENTRY rgAltEntry; DWORD cRaw; DWORD cCount; DWORD cEntry; BOOL fAnyFound = FALSE; CCryptUrlArray cua( 1, 5, fResult ); for ( cRaw = 0; ( fResult == TRUE ) && ( cRaw < cRawUrlData ); cRaw++ ) { pDistPointsInfo = (PCRL_DIST_POINTS_INFO)aRawUrlData[cRaw].pvData; if ( pDistPointsInfo != NULL ) { rgDistPoint = pDistPointsInfo->rgDistPoint; for ( cCount = 0; ( cCount < pDistPointsInfo->cDistPoint ) && ( fResult == TRUE ); cCount++ ) { // Assumption:: don't support partial reasons // For now, will ignore CRL issuers, they might // be the same as the cert's issuer. That was the case // with a Netscape CDP if (rgDistPoint[cCount].ReasonFlags.cbData) continue; pDistPointName = &rgDistPoint[cCount].DistPointName; if ( pDistPointName->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME ) { rgAltEntry = pDistPointName->FullName.rgAltEntry; for ( cEntry = 0; ( fResult == TRUE ) && ( cEntry < pDistPointName->FullName.cAltEntry ); cEntry++ ) { switch (rgAltEntry[cEntry].dwAltNameChoice) { case CERT_ALT_NAME_URL: fResult = cua.AddUrl( rgAltEntry[cEntry].pwszURL, TRUE ); fAnyFound = TRUE; break; case CERT_ALT_NAME_DIRECTORY_NAME: fResult = AddUrlsFromCDPDirectoryName( &rgAltEntry[cEntry].DirectoryName, &cua ); fAnyFound = TRUE; break; default: break; } } } } } } if ( ( fAnyFound == FALSE ) && ( fResult == TRUE ) ) { SetLastError( (DWORD) CRYPT_E_NOT_FOUND ); fResult = FALSE; } if ( fResult == TRUE ) { PCRYPT_URL_ARRAY* ppUrlArray = NULL; if ( pUrlArray != NULL ) { ppUrlArray = &pUrlArray; } fResult = cua.GetArrayInSingleBufferEncodedForm( ppUrlArray, pcbUrlArray ); } if ( ( fResult == TRUE ) && ( pcbUrlInfo != NULL ) ) { InitializeDefaultUrlInfo( pUrlInfo, pcbUrlInfo ); } cua.FreeArray( TRUE ); return( fResult ); } //+--------------------------------------------------------------------------- // // Function: GetUrlArrayAndInfoFromNextUpdateLocation // // Synopsis: get URL data using decoded next update location data // //---------------------------------------------------------------------------- BOOL WINAPI GetUrlArrayAndInfoFromNextUpdateLocation ( IN DWORD cRawUrlData, IN PCRYPT_RAW_URL_DATA aRawUrlData, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo ) { BOOL fResult = FALSE; PCERT_ALT_NAME_INFO pAltNameInfo; PCERT_ALT_NAME_ENTRY rgAltEntry; DWORD cRaw; DWORD cEntry; BOOL fAnyFound = FALSE; CCryptUrlArray cua( 1, 5, fResult ); for ( cRaw = 0; ( fResult == TRUE ) && ( cRaw < cRawUrlData ); cRaw++ ) { pAltNameInfo = (PCERT_ALT_NAME_INFO)aRawUrlData[cRaw].pvData; if ( pAltNameInfo != NULL ) { rgAltEntry = pAltNameInfo->rgAltEntry; for ( cEntry = 0; ( cEntry < pAltNameInfo->cAltEntry ) && ( fResult == TRUE ); cEntry++ ) { if ( rgAltEntry[cEntry].dwAltNameChoice == CERT_ALT_NAME_URL ) { fResult = cua.AddUrl( rgAltEntry[cEntry].pwszURL, TRUE ); fAnyFound = TRUE; } } } } if ( ( fAnyFound == FALSE ) && ( fResult == TRUE ) ) { SetLastError( (DWORD) CRYPT_E_NOT_FOUND ); fResult = FALSE; } if ( fResult == TRUE ) { PCRYPT_URL_ARRAY* ppUrlArray = NULL; if ( pUrlArray != NULL ) { ppUrlArray = &pUrlArray; } fResult = cua.GetArrayInSingleBufferEncodedForm( ppUrlArray, pcbUrlArray ); } if ( ( fResult == TRUE ) && ( pcbUrlInfo != NULL ) ) { InitializeDefaultUrlInfo( pUrlInfo, pcbUrlInfo ); } cua.FreeArray( TRUE ); return( fResult ); } //+--------------------------------------------------------------------------- // // Function: CopyUrlArray // // Synopsis: copy URL array // //---------------------------------------------------------------------------- BOOL WINAPI CopyUrlArray ( IN PCRYPT_URL_ARRAY pDest, IN PCRYPT_URL_ARRAY pSource, IN DWORD cbDest ) { DWORD cCount; DWORD cb; DWORD cbStruct; DWORD cbPointers; DWORD cbUrl; cbStruct = sizeof( CRYPT_URL_ARRAY ); cbPointers = pSource->cUrl * sizeof( LPWSTR ); if (cbDest < (cbStruct + cbPointers)) { SetLastError( (DWORD) E_INVALIDARG ); return FALSE; } pDest->cUrl = pSource->cUrl; pDest->rgwszUrl = (LPWSTR *)( (LPBYTE)pDest + cbStruct ); for ( cCount = 0, cb = 0; cCount < pSource->cUrl; cCount++ ) { pDest->rgwszUrl[cCount] = (LPWSTR)((LPBYTE)pDest+cbStruct+cbPointers+cb); cbUrl = ( wcslen( pSource->rgwszUrl[cCount] ) + 1 ) * sizeof( WCHAR ); if (cbDest < (cbStruct + cbPointers + cb + cbUrl)) { SetLastError( (DWORD) E_INVALIDARG ); return FALSE; } memcpy( pDest->rgwszUrl[cCount], pSource->rgwszUrl[cCount], cbUrl ); cb += cbUrl; } return TRUE; } //+--------------------------------------------------------------------------- // // Function: GetUrlArrayIndex // // Synopsis: get index of an URL in the URL array // //---------------------------------------------------------------------------- VOID WINAPI GetUrlArrayIndex ( IN PCRYPT_URL_ARRAY pUrlArray, IN LPWSTR pwszUrl, IN DWORD DefaultIndex, OUT DWORD* pUrlIndex, OUT BOOL* pfHintInArray ) { DWORD cCount; if ( pUrlIndex != NULL ) { *pUrlIndex = DefaultIndex; } if ( pfHintInArray != NULL ) { *pfHintInArray = FALSE; } if ( pwszUrl == NULL ) { return; } for ( cCount = 0; cCount < pUrlArray->cUrl; cCount++ ) { if ( wcscmp( pUrlArray->rgwszUrl[cCount], pwszUrl ) == 0 ) { if ( pUrlIndex != NULL ) { *pUrlIndex = cCount; } if ( pfHintInArray != NULL ) { *pfHintInArray = TRUE; } break; } } } //+--------------------------------------------------------------------------- // // Function: GetUrlArrayAndInfoFromCrossCertDistPoint // // Synopsis: get URL data using decoded Cross Cert distribution point info // //---------------------------------------------------------------------------- BOOL WINAPI GetUrlArrayAndInfoFromCrossCertDistPoint ( IN DWORD cRawUrlData, IN PCRYPT_RAW_URL_DATA aRawUrlData, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo ) { BOOL fResult = FALSE; PCROSS_CERT_DIST_POINTS_INFO pDistPointsInfo; PCERT_ALT_NAME_INFO rgDistPoint; PCERT_ALT_NAME_ENTRY rgAltEntry; DWORD cRaw; DWORD cCount; DWORD cEntry; BOOL fAnyFound = FALSE; CCryptUrlArray cua( 1, 5, fResult ); DWORD dwSyncDeltaTime = 0; DWORD cMaxGroup = 0; DWORD cGroup = 0; DWORD *pcGroupEntry = NULL; DWORD cGroupEntry; DWORD cbUrlInfo; // Get maximum number of groups for ( cRaw = 0; cRaw < cRawUrlData; cRaw++ ) { pDistPointsInfo = (PCROSS_CERT_DIST_POINTS_INFO)aRawUrlData[cRaw].pvData; if ( pDistPointsInfo != NULL ) { cMaxGroup += pDistPointsInfo->cDistPoint; } } if (cMaxGroup > 0) { pcGroupEntry = new DWORD [cMaxGroup]; if ( pcGroupEntry == NULL) { fResult = FALSE; SetLastError( (DWORD) E_OUTOFMEMORY ); } } for ( cRaw = 0; ( fResult == TRUE ) && ( cRaw < cRawUrlData ); cRaw++ ) { pDistPointsInfo = (PCROSS_CERT_DIST_POINTS_INFO)aRawUrlData[cRaw].pvData; if ( pDistPointsInfo != NULL ) { if ( dwSyncDeltaTime == 0 ) { dwSyncDeltaTime = pDistPointsInfo->dwSyncDeltaTime; } rgDistPoint = pDistPointsInfo->rgDistPoint; for ( cCount = 0; ( cCount < pDistPointsInfo->cDistPoint ) && ( fResult == TRUE ); cCount++ ) { rgAltEntry = rgDistPoint[cCount].rgAltEntry; cGroupEntry = 0; for ( cEntry = 0; ( fResult == TRUE ) && ( cEntry < rgDistPoint[cCount].cAltEntry ); cEntry++ ) { switch (rgAltEntry[cEntry].dwAltNameChoice) { case CERT_ALT_NAME_URL: fResult = cua.AddUrl( rgAltEntry[cEntry].pwszURL, TRUE ); fAnyFound = TRUE; cGroupEntry++; break; default: break; } } if ( cGroupEntry > 0 ) { if (cGroup < cMaxGroup) { pcGroupEntry[cGroup] = cGroupEntry; cGroup++; } else { fResult = FALSE; SetLastError( (DWORD) E_UNEXPECTED ); } } } } } if ( ( fAnyFound == FALSE ) && ( fResult == TRUE ) ) { SetLastError( (DWORD) CRYPT_E_NOT_FOUND ); fResult = FALSE; } if ( fResult == TRUE ) { PCRYPT_URL_ARRAY* ppUrlArray = NULL; if ( pUrlArray != NULL ) { ppUrlArray = &pUrlArray; } fResult = cua.GetArrayInSingleBufferEncodedForm( ppUrlArray, pcbUrlArray ); } if ( ( fResult == TRUE ) && ( pcbUrlInfo != NULL ) ) { cbUrlInfo = sizeof( CRYPT_URL_INFO ) + cGroup * sizeof(DWORD); if ( pUrlInfo != NULL ) { if (*pcbUrlInfo < cbUrlInfo) { fResult = FALSE; SetLastError( (DWORD) E_INVALIDARG ); } else { pUrlInfo->cbSize = sizeof( CRYPT_URL_INFO ); pUrlInfo->dwSyncDeltaTime = dwSyncDeltaTime; pUrlInfo->cGroup = cGroup; if ( cGroup > 0 ) { pUrlInfo->rgcGroupEntry = (DWORD *) &pUrlInfo[ 1 ]; memcpy(pUrlInfo->rgcGroupEntry, pcGroupEntry, cGroup * sizeof(DWORD)); } else { pUrlInfo->rgcGroupEntry = NULL; } } } *pcbUrlInfo = cbUrlInfo; } cua.FreeArray( TRUE ); if (pcGroupEntry) { delete [] pcGroupEntry; } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: CertificateCrossCertDistPointGetObjectUrl // // Synopsis: get certificate cross certificate URL // //---------------------------------------------------------------------------- BOOL WINAPI CertificateCrossCertDistPointGetObjectUrl( IN LPCSTR pszUrlOid, IN LPVOID pvPara, IN DWORD dwFlags, OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray, IN OUT DWORD* pcbUrlArray, OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo, IN OUT OPTIONAL DWORD* pcbUrlInfo, IN LPVOID pvReserved ) { BOOL fResult = FALSE; CRYPT_RAW_URL_DATA RawData[MAX_RAW_URL_DATA]; ULONG cRawData = MAX_RAW_URL_DATA; fResult = ObjectContextGetRawUrlData( CONTEXT_OID_CERTIFICATE, pvPara, (DWORD) -1L, // Index dwFlags, szOID_CROSS_CERT_DIST_POINTS, RawData, &cRawData ); if ( fResult == TRUE ) { fResult = GetUrlArrayAndInfoFromCrossCertDistPoint( cRawData, RawData, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo ); ObjectContextFreeRawUrlData( cRawData, RawData ); } return( fResult ); }