//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1998 // // File: tcrobu.cpp // // Contents: CryptRetrieveObjectByUrl tests // // History: 27-May-97 kirtd Created // //---------------------------------------------------------------------------- #include #include #include "wincrypt.h" #include "certtest.h" #include #include #include #include #include #include #include #include typedef BYTE CRYPT_ORIGIN_IDENTIFIER[MD5DIGESTLEN]; BYTE Foo[300]; BYTE Bar[300]; DWORD g_dwCount = 0; //+--------------------------------------------------------------------------- // // Function: Usage // // Synopsis: prints the usage statement // //---------------------------------------------------------------------------- static void Usage(void) { printf("Usage: tcrobu URL [ObjectOid] [-m] [-c] [-s] [-w] [-l]\n"); printf(" URL, locator to retrieve from\n"); printf(" ObjectOid, a cert, crl, or ctl, if omitted, retrieve bits\n"); printf(" -m, retrieve multiple objects\n"); printf(" -c, cache only retrieval\n"); printf(" -d, do not cache the result\n"); printf(" -w, wire only retrieval\n"); printf(" -u, CryptGetObjectUrl on the result context\n"); printf(" -l, logon user credentials \n"); printf(" -t, timeout\n"); printf(" -f, install cancel function\n"); printf(" -n, install and uninstall cancel function\n"); printf(" -r, the # of times the cancel function should be called\n"); printf(" -v, verbose display\n"); printf(" -q, quiet display\n"); printf(" -s, save to serialized store file\n"); printf(" -7, save to PKCS7 store file\n"); printf(" -a, get AuxInfo\n"); printf(" -p, sticky persist\n"); printf(" -e, prepend LDAP entry and attribute\n"); printf(" -k, Kerberos Signing for LDAP\n"); printf(" -i, inhibit authentication\n"); printf(" -Error, expected error\n"); printf(" -Flags, retrieval flags to be OR'ed\n"); printf(" -Size, maximum retrieval byte count\n"); } //+--------------------------------------------------------------------------- // // Function: CertGetOriginIdentifier // // Synopsis: get the origin identifier for a certificate // //---------------------------------------------------------------------------- BOOL WINAPI CertGetOriginIdentifier ( IN PCCERT_CONTEXT pCertContext, IN PCCERT_CONTEXT pIssuer, IN DWORD dwFlags, OUT CRYPT_ORIGIN_IDENTIFIER OriginIdentifier ) { MD5_CTX md5ctx; PCERT_INFO pCertInfo = pCertContext->pCertInfo; PCERT_INFO pIssuerCertInfo = pIssuer->pCertInfo; MD5Init( &md5ctx ); MD5Update( &md5ctx, pCertInfo->Issuer.pbData, pCertInfo->Issuer.cbData ); MD5Update( &md5ctx, pCertInfo->Subject.pbData, pCertInfo->Subject.cbData ); MD5Update( &md5ctx, (LPBYTE)pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, strlen( pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId ) ); MD5Update( &md5ctx, pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData, pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData ); // We assume that the unused public key bits are zero MD5Update( &md5ctx, pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData ); MD5Update( &md5ctx, pIssuerCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pIssuerCertInfo->SubjectPublicKeyInfo.PublicKey.cbData ); MD5Final( &md5ctx ); memcpy( OriginIdentifier, md5ctx.digest, MD5DIGESTLEN ); return( TRUE ); } //+--------------------------------------------------------------------------- // // Function: MyCancelFunction // // Synopsis: The call back function to cancel the object retrieval. // The cancellation happens when it is called for the 3rd time. // //---------------------------------------------------------------------------- BOOL WINAPI MyCancelFunction(DWORD dwFlags, void *pvArg) { DWORD *pCount=NULL; pCount=(DWORD *)pvArg; if(*pCount == g_dwCount) return TRUE; (*pCount)++; return FALSE; } //+--------------------------------------------------------------------------- // // Function: main // // Synopsis: main program entry point // //---------------------------------------------------------------------------- int _cdecl main(int argc, char * argv[]) { #if 0 BOOL fResult; HINTERNET hInetSession; hInetSession = InternetOpen( "foo", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); if ( hInetSession == NULL ) { printf("Error opening internet session %lx\n", GetLastError()); return( 1 ); } fResult = InternetSetOption( hInetSession, INTERNET_OPTION_USERNAME, "foo", strlen( "foo" ) + 1 ); if ( fResult == TRUE ) { fResult = InternetSetOption( hInetSession, INTERNET_OPTION_PROXY_USERNAME, "bar", strlen( "bar" ) + 1 ); } if ( fResult == TRUE ) { fResult = InternetSetOption( hInetSession, INTERNET_OPTION_PASSWORD, "gamma", strlen( "gamma" ) + 1 ); if ( fResult == TRUE ) { fResult = InternetSetOption( hInetSession, INTERNET_OPTION_PROXY_PASSWORD, "beta", strlen( "beta" ) + 1 ); } } InternetCloseHandle( hInetSession ); return( 0 ); #endif #if 0 LPWSTR pwszUrl = NULL; if ( I_CryptNetGetUserDsStoreUrl( L"X509Certificate", &pwszUrl ) == TRUE ) { wprintf(L"User DS Store URL = <%s>\n", pwszUrl); CryptMemFree( pwszUrl ); } else { printf("I_CryptNetGetUserDsStoreUrl failed <%lx>\n", GetLastError()); } return( 0 ); #endif #if 1 ULONG cCount; PCRYPT_BLOB_ARRAY pcba; LPVOID pv; LPSTR pszObjectOid = NULL; LPSTR pszUrl = NULL; LPSTR pszUsername = NULL; LPSTR pszPassword = NULL; DWORD dwRetrievalFlags = 0; BOOL fGetObjectUrl = FALSE; PCRYPT_CREDENTIALS pCredentials = NULL; CRYPT_CREDENTIALS Credentials; CRYPT_PASSWORD_CREDENTIALSA PasswordCredentials; CRYPT_PASSWORD_CREDENTIALSW UnicodePasswordCredentials; BOOL fUnicodeCredentials = FALSE; LPWSTR pwszUsername = NULL; LPWSTR pwszPassword = NULL; DWORD dwTimeout = 0; BOOL fCancel = FALSE; BOOL fUninstall = FALSE; DWORD dwCount = 0; BOOL fQuiet = FALSE; DWORD dwDisplayFlags = 0; BOOL fSave = FALSE; BOOL fPKCS7Save = FALSE; LPSTR pszSaveFilename = NULL; DWORD dwExpectedError = 0; PCRYPT_RETRIEVE_AUX_INFO pAuxInfo = NULL; FILETIME LastSyncTime = { 0, 0 }; CRYPT_RETRIEVE_AUX_INFO AuxInfo; memset(&AuxInfo, 0, sizeof(AuxInfo)); AuxInfo.cbSize = sizeof(AuxInfo); if ( argc < 2 ) { Usage(); return( 1 ); } argv++; argc--; printf( "command line: %s\n", GetCommandLineA() ); pszUrl = argv[0]; while ( --argc > 0 ) { if (**++argv == '-') { if (0 == _stricmp(argv[0]+1, "Error")) { if ( argc < 2 ) { Usage(); return( 1 ); } dwExpectedError = (DWORD) strtoul(argv[1], NULL, 0); argc -= 1; argv++; } else if (0 == _stricmp(argv[0]+1, "Flags")) { if ( argc < 2 ) { Usage(); return( 1 ); } dwRetrievalFlags |= (DWORD) strtoul(argv[1], NULL, 0); argc -= 1; argv++; } else if (0 == _stricmp(argv[0]+1, "Size")) { if ( argc < 2 ) { Usage(); return( 1 ); } pAuxInfo = &AuxInfo; AuxInfo.dwMaxUrlRetrievalByteCount = (DWORD) strtoul(argv[1], NULL, 0); argc -= 1; argv++; } else { switch(argv[0][1]) { case 'm': case 'M': dwRetrievalFlags |= CRYPT_RETRIEVE_MULTIPLE_OBJECTS; break; case 'c': case 'C': dwRetrievalFlags |= CRYPT_CACHE_ONLY_RETRIEVAL; break; case 'w': case 'W': dwRetrievalFlags |= CRYPT_WIRE_ONLY_RETRIEVAL; break; case 'f': case 'F': fCancel = TRUE; break; case 'n': case 'N': fUninstall = TRUE; break; case 'd': case 'D': dwRetrievalFlags |= CRYPT_DONT_CACHE_RESULT; break; case 'u': case 'U': fGetObjectUrl = TRUE; break; case 't': case 'T': if ( argc < 2 ) { Usage(); return( 1 ); } dwTimeout = atol( argv[1] ); argc -= 1; argv++; break; case 'r': case 'R': if ( argc < 2 ) { Usage(); return( 1 ); } g_dwCount = atol( argv[1] ); argc -= 1; argv++; break; case 'L': fUnicodeCredentials = TRUE; case 'l': if ( argc < 2 ) { Usage(); return( 1 ); } pszUsername = argv[1]; if ( argc > 2 ) { pszPassword = argv[2]; argc--; argv++; } argc -= 1; argv++; break; case 'q': case 'Q': fQuiet = TRUE; break; case 'v': case 'V': dwDisplayFlags |= DISPLAY_VERBOSE_FLAG; break; case '7': fPKCS7Save = TRUE; case 's': case 'S': fSave = TRUE; if ( argc < 2 ) { Usage(); return( 1 ); } pszSaveFilename = argv[1]; argc -= 1; argv++; break; case 'a': case 'A': pAuxInfo = &AuxInfo; AuxInfo.pLastSyncTime = &LastSyncTime; break; case 'p': case 'P': dwRetrievalFlags |= CRYPT_STICKY_CACHE_RETRIEVAL; break; case 'e': case 'E': dwRetrievalFlags |= CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE; break; case 'k': case 'K': dwRetrievalFlags |= CRYPT_LDAP_SIGN_RETRIEVAL; break; case 'i': case 'I': dwRetrievalFlags |= CRYPT_NO_AUTH_RETRIEVAL; break; default: Usage(); return -1; } } } else { if ( _stricmp( argv[0], "cert" ) == 0 ) { pszObjectOid = (LPSTR)CONTEXT_OID_CERTIFICATE; } else if ( _stricmp( argv[0], "ctl" ) == 0 ) { pszObjectOid = (LPSTR)CONTEXT_OID_CTL; } else if ( _stricmp( argv[0], "crl" ) == 0 ) { pszObjectOid = (LPSTR)CONTEXT_OID_CRL; } else if ( _stricmp( argv[0], "pkcs7" ) == 0 ) { pszObjectOid = (LPSTR)CONTEXT_OID_PKCS7; } else if ( _stricmp( argv[0], "any" ) == 0 ) { pszObjectOid = (LPSTR)CONTEXT_OID_CAPI2_ANY; } else { Usage(); return( -1 ); } } } if ( pszUsername != NULL ) { if (fUnicodeCredentials) { pwszUsername = AllocAndSzToWsz(pszUsername); if ( pszPassword != NULL ) { pwszPassword = AllocAndSzToWsz(pszPassword); } UnicodePasswordCredentials.cbSize = sizeof( UnicodePasswordCredentials ); UnicodePasswordCredentials.pszUsername = pwszUsername; UnicodePasswordCredentials.pszPassword = pwszPassword; Credentials.cbSize = sizeof( Credentials ); Credentials.pszCredentialsOid = CREDENTIAL_OID_PASSWORD_CREDENTIALS_W; Credentials.pvCredentials = (LPVOID)&UnicodePasswordCredentials; pCredentials = &Credentials; printf("Using Unicode credentials %S <%S>\n", pwszUsername, pwszPassword); } else { PasswordCredentials.cbSize = sizeof( PasswordCredentials ); PasswordCredentials.pszUsername = pszUsername; PasswordCredentials.pszPassword = pszPassword; Credentials.cbSize = sizeof( Credentials ); Credentials.pszCredentialsOid = CREDENTIAL_OID_PASSWORD_CREDENTIALS_A; Credentials.pvCredentials = (LPVOID)&PasswordCredentials; pCredentials = &Credentials; printf("Using credentials %s <%s>\n", pszUsername, pszPassword); } } if(fCancel) { if(!CryptInstallCancelRetrieval( MyCancelFunction, &dwCount, 0, NULL)) printf("Install cancel function failed!\n"); if(fUninstall) { if(!CryptUninstallCancelRetrieval( 0, NULL)) printf("Uninstall cancel function failed!\n"); } } if ( CryptRetrieveObjectByUrlA( pszUrl, pszObjectOid, dwRetrievalFlags, dwTimeout, &pv, NULL, pCredentials, NULL, pAuxInfo ) == FALSE ) { DWORD dwLastErr = GetLastError(); if (0 == dwExpectedError) printf( "CryptRetrieveObjectByUrl FAILED! <0x%x %d>\n", dwLastErr, dwLastErr ); else if (dwLastErr != dwExpectedError) printf( "CryptRetrieveObjectByUrl FAILED! Expected: 0x%x Actual: <0x%x %d>\n", dwExpectedError, dwLastErr, dwLastErr ); else printf( "CryptRetrieveObjectByUrl SUCCEEDED! Got Expected: <0x%x %d>\n", dwLastErr, dwLastErr ); if(fCancel) { if(!fUninstall) { if(!CryptUninstallCancelRetrieval( 0, NULL)) printf("Uninstall cancel function failed!\n"); } } if (pwszUsername) TestFree(pwszUsername); if (pwszPassword) TestFree(pwszPassword); return( -1 ); } if (0 == dwExpectedError) printf( "CryptRetrieveObjectByUrl SUCCEEDED!\n" ); else printf( "CryptRetrieveObjectByUrl FAILED! Expected: 0x%x Actual: 0x0\n", dwExpectedError ); if (pAuxInfo) { printf(" LastSyncTime:: %s\n", FileTimeText(&LastSyncTime)); } if(fCancel) { if(!fUninstall) { if(!CryptUninstallCancelRetrieval( 0, NULL)) printf("Uninstall cancel function failed!\n"); } } if ( pszObjectOid == NULL ) { pcba = (PCRYPT_BLOB_ARRAY)pv; for ( cCount = 0; cCount < pcba->cBlob; cCount++ ) { PBYTE pb = pcba->rgBlob[cCount].pbData; DWORD cb = pcba->rgBlob[cCount].cbData; printf( "\nObject#%d ", cCount+1); if (dwRetrievalFlags & CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE) { DWORD cbPrefix; LPCSTR pszIndex; LPCSTR pszAttr; pszIndex = (LPCSTR) pb; cbPrefix = strlen(pszIndex) + 1; pb += cbPrefix; cb -= cbPrefix; pszAttr = (LPCSTR) pb; cbPrefix = strlen(pszAttr) + 1; pb += cbPrefix; cb -= cbPrefix; printf("[%s, %s] ", pszIndex, pszAttr); } printf( "- Length=0x%lx\n", cb ); PrintBytes( "", pb, cb ); } CryptMemFree( pv ); } else if ( pszObjectOid == CONTEXT_OID_CERTIFICATE ) { if ( !( dwRetrievalFlags & CRYPT_RETRIEVE_MULTIPLE_OBJECTS ) ) { DisplayCert( (PCCERT_CONTEXT)pv, dwDisplayFlags ); if ( fGetObjectUrl == TRUE ) { #if 1 DWORD cbUrlArray; if ( CryptGetObjectUrl( URL_OID_CERTIFICATE_CRL_DIST_POINT, pv, 0, NULL, &cbUrlArray, NULL, NULL, NULL ) == FALSE ) { printf("GetObjectUrl failed %lx\n", GetLastError()); } else { printf("cbUrlArray = %ld\n", cbUrlArray); } #else DWORD cCount; LARGE_INTEGER TickCount1; LARGE_INTEGER TickCount2; LARGE_INTEGER TickCount; CRYPT_ORIGIN_IDENTIFIER OriginIdentifier; #define NUM_ITER 1000000 GetSystemTimeAsFileTime( (LPFILETIME)&TickCount1 ); for ( cCount = 0; cCount < NUM_ITER; cCount++ ) { if ( memcmp( Foo, Bar, 100 ) != 0 ) { Foo[0] = 1; Bar[0] = 1; } if ( memcmp( Foo, Bar, 200 ) != 0 ) { Foo[0] = 1; Bar[0] = 1; } if ( memcmp( Foo, Bar, 64 ) != 0 ) { Foo[0] = 1; Bar[0] = 1; } if ( memcmp( Foo, Bar, 128 ) != 0 ) { Foo[0] = 1; Bar[0] = 1; } //CertGetOriginIdentifier( // (PCCERT_CONTEXT)pv, // (PCCERT_CONTEXT)pv, // 0, // OriginIdentifier // ); } GetSystemTimeAsFileTime( (LPFILETIME)&TickCount2 ); TickCount.QuadPart = ( TickCount2.QuadPart - TickCount1.QuadPart ); printf("PerIter = %ld ns. Total = %ld s.\n", (((LPFILETIME)&TickCount)->dwLowDateTime / NUM_ITER) * 100, ((LPFILETIME)&TickCount)->dwLowDateTime / 10000000); #endif } CertFreeCertificateContext( (PCCERT_CONTEXT)pv ); } else { if (!fQuiet) DisplayStore( (HCERTSTORE)pv, dwDisplayFlags ); if (fSave && pszSaveFilename) SaveStoreEx( (HCERTSTORE)pv, fPKCS7Save, pszSaveFilename); CertCloseStore( (HCERTSTORE)pv, 0 ); } } else if ( pszObjectOid == CONTEXT_OID_CTL ) { if ( !( dwRetrievalFlags & CRYPT_RETRIEVE_MULTIPLE_OBJECTS ) ) { DisplayCtl( (PCCTL_CONTEXT)pv, dwDisplayFlags ); CertFreeCTLContext( (PCCTL_CONTEXT)pv ); } else { if (!fQuiet) DisplayStore( (HCERTSTORE)pv, dwDisplayFlags ); if (fSave && pszSaveFilename) SaveStoreEx( (HCERTSTORE)pv, fPKCS7Save, pszSaveFilename); CertCloseStore( (HCERTSTORE)pv, 0 ); } } else if ( pszObjectOid == CONTEXT_OID_CRL ) { if ( !( dwRetrievalFlags & CRYPT_RETRIEVE_MULTIPLE_OBJECTS ) ) { DisplayCrl( (PCCRL_CONTEXT)pv, dwDisplayFlags ); CertFreeCRLContext( (PCCRL_CONTEXT)pv ); } else { if (!fQuiet) DisplayStore( (HCERTSTORE)pv, dwDisplayFlags ); if (fSave && pszSaveFilename) SaveStoreEx( (HCERTSTORE)pv, fPKCS7Save, pszSaveFilename); CertCloseStore( (HCERTSTORE)pv, 0 ); } } else if ( ( pszObjectOid == CONTEXT_OID_CAPI2_ANY ) || ( pszObjectOid == CONTEXT_OID_PKCS7 ) ) { if (!fQuiet) DisplayStore( (HCERTSTORE)pv, dwDisplayFlags ); if (fSave && pszSaveFilename) SaveStoreEx( (HCERTSTORE)pv, fPKCS7Save, pszSaveFilename); CertCloseStore( (HCERTSTORE)pv, 0 ); } if (pwszUsername) TestFree(pwszUsername); if (pwszPassword) TestFree(pwszPassword); return( 0 ); #endif }