//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: certmap.c // // Contents: Routines to call appropriate mapper, be it the system // default one (in the LSA process) or an application one (in // the application process). // // Classes: // // Functions: // // History: 12-23-96 jbanes Created. // //---------------------------------------------------------------------------- #include DWORD WINAPI SslReferenceMapper(HMAPPER *phMapper) { DWORD dwResult; SecBuffer Input; SecBuffer Output; SECURITY_STATUS scRet; if(phMapper == NULL) { return SP_LOG_RESULT(-1); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. return phMapper->m_vtable->ReferenceMapper(phMapper); } else { // Application mapper. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = 0; Input.pvBuffer = NULL; scRet = PerformApplicationCallback( SCH_REFERENCE_MAPPER_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, TRUE, &Input, &Output, TRUE); if(!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR, "Error 0x%x referencing mapper\n", scRet)); return SP_LOG_RESULT(scRet); } SP_ASSERT(Output.cbBuffer == sizeof(DWORD)); dwResult = *(PDWORD)(Output.pvBuffer); SPExternalFree(Output.pvBuffer); return dwResult; } } DWORD WINAPI SslDereferenceMapper(HMAPPER *phMapper) { DWORD dwResult; SecBuffer Input; SecBuffer Output; SECURITY_STATUS scRet; if(phMapper == NULL) { return SP_LOG_RESULT(0); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. return phMapper->m_vtable->DeReferenceMapper(phMapper); } else { // Application mapper. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = 0; Input.pvBuffer = NULL; scRet = PerformApplicationCallback( SCH_REFERENCE_MAPPER_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, FALSE, &Input, &Output, TRUE); if(!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR, "Error 0x%x dereferencing mapper\n", scRet)); return SP_LOG_RESULT(scRet); } SP_ASSERT(Output.cbBuffer == sizeof(DWORD)); dwResult = *(PDWORD)(Output.pvBuffer); SPExternalFree(Output.pvBuffer); return dwResult; } } //+--------------------------------------------------------------------------- // // Function: ReferenceMapperCallback // // Synopsis: Reference (or dereference) the application mapper. // // Arguments: [fReference] -- Whether to reference or dereference. // [dwArg2] -- Not used. // [pInput] -- HMAPPER structure. // [pOutput] -- DWORD reference count. // // History: 10-17-97 jbanes Created // // Notes: // //---------------------------------------------------------------------------- SECURITY_STATUS ReferenceMapperCallback( ULONG_PTR Mapper, ULONG_PTR fReference, SecBuffer *pInput, SecBuffer *pOutput) { DWORD dwResult; HMAPPER *phMapper; if(!SchannelInit(TRUE)) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } DebugLog((DEB_TRACE, "ReferenceMapperCallback\n")); phMapper = (HMAPPER *)Mapper; // Perform reference counting. try { if(fReference) { dwResult = phMapper->m_vtable->ReferenceMapper(phMapper); } else { dwResult = phMapper->m_vtable->DeReferenceMapper(phMapper); } } except(EXCEPTION_EXECUTE_HANDLER) { return SP_LOG_RESULT(SEC_E_INVALID_HANDLE); } // Build output buffer pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = sizeof(DWORD); pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer); if(pOutput->pvBuffer == NULL) { return SEC_E_INSUFFICIENT_MEMORY; } *(DWORD *)(pOutput->pvBuffer) = dwResult; return SEC_E_OK; } SECURITY_STATUS WINAPI SslGetMapperIssuerList( HMAPPER * phMapper, // in BYTE ** ppIssuerList, // out DWORD * pcbIssuerList) // out { SecBuffer Input; SecBuffer Output; SECURITY_STATUS Status; if(phMapper == NULL) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. Status = phMapper->m_vtable->GetIssuerList(phMapper, 0, NULL, pcbIssuerList); if(!NT_SUCCESS(Status)) { return SP_LOG_RESULT(Status); } *ppIssuerList = SPExternalAlloc(*pcbIssuerList); if(*ppIssuerList == NULL) { return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); } Status = phMapper->m_vtable->GetIssuerList(phMapper, 0, *ppIssuerList, pcbIssuerList); if(!NT_SUCCESS(Status)) { SPExternalFree(*ppIssuerList); return SP_LOG_RESULT(Status); } return Status; } else { // Application mapper. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = 0; Input.pvBuffer = NULL; Status = PerformApplicationCallback( SCH_GET_MAPPER_ISSUER_LIST_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, 0, &Input, &Output, TRUE); if(!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR, "Error 0x%x getting mapper issuer list\n", Status)); *ppIssuerList = NULL; *pcbIssuerList = 0; return Status; } *ppIssuerList = Output.pvBuffer; *pcbIssuerList = Output.cbBuffer; return Status; } } //+--------------------------------------------------------------------------- // // Function: GetMapperIssuerListCallback // // Synopsis: Query the application mapper for the list of trusted CAs. // // Arguments: [pIssuerList] -- Pointer to LSA buffer. // [cbIssuerList] -- Size of LSA buffer. // [pInput] -- HMAPPER structure. // [pOutput] -- Issuer list. // // History: 10-17-97 jbanes Created // // Notes: The format of the output buffer is as follows: // // BYTE rgbIssuerList; // //---------------------------------------------------------------------------- SECURITY_STATUS GetMapperIssuerListCallback( ULONG_PTR Mapper, ULONG_PTR dwArg2, SecBuffer *pInput, SecBuffer *pOutput) { HMAPPER * phMapper; DWORD cbIssuerList; DWORD Status; if(!SchannelInit(TRUE)) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } DebugLog((DEB_TRACE, "GetMapperIssuerListCallback\n")); phMapper = (HMAPPER *)Mapper; pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = 0; pOutput->pvBuffer = NULL; try { Status = phMapper->m_vtable->GetIssuerList(phMapper, NULL, NULL, &cbIssuerList); if(!NT_SUCCESS(Status)) { SP_LOG_RESULT(Status); goto error; } pOutput->cbBuffer = cbIssuerList; pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer); if(pOutput->pvBuffer == NULL) { Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); goto error; } Status = phMapper->m_vtable->GetIssuerList(phMapper, NULL, pOutput->pvBuffer, &cbIssuerList); if(!NT_SUCCESS(Status)) { SP_LOG_RESULT(Status); goto error; } } except(EXCEPTION_EXECUTE_HANDLER) { Status = SP_LOG_RESULT(SEC_E_INVALID_HANDLE); goto error; } return SEC_E_OK; error: if(pOutput->pvBuffer) { FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer); pOutput->pvBuffer = NULL; } return Status; } SECURITY_STATUS WINAPI SslGetMapperChallenge( HMAPPER * phMapper, // in BYTE * pAuthenticatorId, // in DWORD cbAuthenticatorId, // in BYTE * pChallenge, // out DWORD * pcbChallenge) // out { return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION); } SECURITY_STATUS WINAPI SslMapCredential( HMAPPER * phMapper, // in DWORD dwCredentialType, // in PCCERT_CONTEXT pCredential, // in PCCERT_CONTEXT pAuthority, // in HLOCATOR * phLocator) // out { SecBuffer Input; SecBuffer Output; PBYTE pbBuffer; DWORD cbCredential; DWORD cbAuthority; SECURITY_STATUS scRet; if(phMapper == NULL) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. scRet = phMapper->m_vtable->MapCredential(phMapper, dwCredentialType, pCredential, pAuthority, phLocator); return MapWinTrustError(scRet, SEC_E_NO_IMPERSONATION, 0); } else { // Application mapper. // Determine the size of the serialized cert contexts. scRet = SerializeCertContext(pCredential, NULL, &cbCredential); if(FAILED(scRet)) { return SP_LOG_RESULT(scRet); } if(pAuthority) { if(!CertSerializeCertificateStoreElement( pAuthority, 0, NULL, &cbAuthority)) { return SP_LOG_RESULT(GetLastError()); } } else { cbAuthority = 0; } // Allocate memory for the input buffer. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = sizeof(DWORD) + cbCredential + sizeof(DWORD) + cbAuthority; Input.pvBuffer = LocalAlloc(LMEM_FIXED, Input.cbBuffer); if(Input.pvBuffer == NULL) { return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); } // Build the input buffer. pbBuffer = Input.pvBuffer; *(PDWORD)pbBuffer = cbCredential; pbBuffer += sizeof(DWORD); *(PDWORD)pbBuffer = cbAuthority; pbBuffer += sizeof(DWORD); scRet = SerializeCertContext(pCredential, pbBuffer, &cbCredential); if(FAILED(scRet)) { LocalFree(Input.pvBuffer); return SP_LOG_RESULT(scRet); } pbBuffer += cbCredential; if(pAuthority) { if(!CertSerializeCertificateStoreElement( pAuthority, 0, pbBuffer, &cbAuthority)) { scRet = SP_LOG_RESULT(GetLastError()); LocalFree(Input.pvBuffer); return scRet; } pbBuffer += cbAuthority; } SP_ASSERT(pbBuffer - (PBYTE)Input.pvBuffer == (INT)Input.cbBuffer); scRet = PerformApplicationCallback( SCH_MAP_CREDENTIAL_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, dwCredentialType, &Input, &Output, TRUE); LocalFree(Input.pvBuffer); if(!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR, "Error 0x%x mapping credential\n", scRet)); return scRet; } SP_ASSERT(Output.cbBuffer == sizeof(HLOCATOR)); CopyMemory(phLocator, Output.pvBuffer, sizeof(HLOCATOR)); SPExternalFree(Output.pvBuffer); return SEC_E_OK; } } //+--------------------------------------------------------------------------- // // Function: MapCredentialCallback // // Synopsis: Maps the specified certificate to an NT user account, via // an application-installed certificate mapper. // // Arguments: [dwCredentialType] -- Credential type. // [dwArg2] -- Not used. // [pInput] -- See notes. // [pOutput] -- Returned locator. // // History: 12-29-97 jbanes Created // // Notes: The format of the input buffer is: // // DWORD cbCredential; // DWORD cbAuthority; // BYTE rgbCredential[cbCredential]; // BYTE rgbAuthority[cbAuthority]; // // The credential and authority fields consist of serialized // CERT_CONTEXT structures. // //---------------------------------------------------------------------------- SECURITY_STATUS MapCredentialCallback( ULONG_PTR Mapper, ULONG_PTR dwCredentialType, SecBuffer *pInput, SecBuffer *pOutput) { HMAPPER * phMapper; PCCERT_CONTEXT pCredential = NULL; PCCERT_CONTEXT pAuthority = NULL; SECURITY_STATUS scRet; DWORD cbCredential; DWORD cbAuthority; PBYTE pbBuffer; HLOCATOR hLocator; if(!SchannelInit(TRUE)) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } DebugLog((DEB_TRACE, "MapCredentialCallback\n")); phMapper = (HMAPPER *)Mapper; // Initialize output buffer. pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = 0; pOutput->pvBuffer = NULL; // // Parse input buffer // pbBuffer = pInput->pvBuffer; if(pInput->cbBuffer < sizeof(DWORD) * 2) { scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); goto done; } cbCredential = *(PDWORD)pbBuffer; pbBuffer += sizeof(DWORD); cbAuthority = *(PDWORD)pbBuffer; pbBuffer += sizeof(DWORD); if(pInput->cbBuffer < sizeof(DWORD) * 2 + cbCredential + cbAuthority) { scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); goto done; } // Deserialize "credential" certificate context. scRet = DeserializeCertContext(&pCredential, pbBuffer, cbCredential); if(FAILED(scRet)) { scRet = SP_LOG_RESULT(scRet); goto done; } pbBuffer += cbCredential; // Deserialize "authority" certificate context. if(cbAuthority && pCredential->hCertStore) { if(!CertAddSerializedElementToStore(pCredential->hCertStore, pbBuffer + sizeof(DWORD), *(DWORD *)pbBuffer, CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, &pAuthority)) { scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); goto done; } } // // Call application mapper. // try { scRet = phMapper->m_vtable->MapCredential(phMapper, (DWORD)dwCredentialType, pCredential, pAuthority, &hLocator); if(!NT_SUCCESS(scRet)) { // Mapping was unsuccessful. scRet = MapWinTrustError(scRet, SEC_E_NO_IMPERSONATION, 0); goto done; } } except(EXCEPTION_EXECUTE_HANDLER) { return SP_LOG_RESULT(SEC_E_INVALID_HANDLE); } // // Build output buffer // pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = sizeof(HLOCATOR); pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer); if(pOutput->pvBuffer == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto done; } *(HLOCATOR *)(pOutput->pvBuffer) = hLocator; scRet = SEC_E_OK; done: if(pCredential) { CertFreeCertificateContext(pCredential); } if(pAuthority) { CertFreeCertificateContext(pAuthority); } return scRet; } SECURITY_STATUS WINAPI SslCloseLocator( HMAPPER * phMapper, // in HLOCATOR hLocator) // in { SecBuffer Input; SecBuffer Output; SECURITY_STATUS scRet; if(phMapper == NULL) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. return phMapper->m_vtable->CloseLocator(phMapper, hLocator); } else { // Application mapper. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = 0; Input.pvBuffer = NULL; scRet = PerformApplicationCallback( SCH_CLOSE_LOCATOR_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, (ULONG_PTR)hLocator, &Input, &Output, FALSE); if(!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR, "Error 0x%x closing locator\n", scRet)); return scRet; } SP_ASSERT(Output.cbBuffer == 0); return scRet; } } //+--------------------------------------------------------------------------- // // Function: CloseLocatorCallback // // Synopsis: Reference (or dereference) the application mapper. // // Arguments: [hLocator] -- Handle to locator. // [dwArg2] -- Not used. // [pInput] -- HMAPPER structure. // [pOutput] -- Not used. // // History: 12-28-97 jbanes Created // // Notes: // //---------------------------------------------------------------------------- SECURITY_STATUS CloseLocatorCallback( ULONG_PTR Mapper, ULONG_PTR hLocator, SecBuffer *pInput, SecBuffer *pOutput) { HMAPPER *phMapper; SECURITY_STATUS Status; if(!SchannelInit(TRUE)) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } DebugLog((DEB_TRACE, "CloseLocatorCallback\n")); phMapper = (HMAPPER *)Mapper; // Close the locator. try { Status = phMapper->m_vtable->CloseLocator(phMapper, hLocator); } except(EXCEPTION_EXECUTE_HANDLER) { return SP_LOG_RESULT(SEC_E_INVALID_HANDLE); } // Build output buffer pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = 0; pOutput->pvBuffer = NULL; return Status; } SECURITY_STATUS WINAPI SslQueryMappedCredentialAttributes( HMAPPER * phMapper, // in HLOCATOR hLocator, // in DWORD dwAttribute, // in PVOID * ppBuffer) // out { SecBuffer Input; SecBuffer Output; SECURITY_STATUS scRet; if(phMapper == NULL) { return SP_LOG_RESULT(SEC_E_INVALID_HANDLE); } if(phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER) { // System mapper. return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION); } else { // Application mapper. Input.BufferType = SECBUFFER_DATA; Input.cbBuffer = sizeof(DWORD); Input.pvBuffer = &dwAttribute; scRet = PerformApplicationCallback( SCH_GET_MAPPER_ATTRIBUTES_CALLBACK, (ULONG_PTR)phMapper->m_Reserved1, hLocator, &Input, &Output, TRUE); if(!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR, "Error 0x%x querying mapped attribute.\n", scRet)); return scRet; } if(Output.cbBuffer != sizeof(PVOID)) { SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } *ppBuffer = *(PVOID *)Output.pvBuffer; SPExternalFree(Output.pvBuffer); //this is allocated by SPExternalAlloc() return SEC_E_OK; } } //+--------------------------------------------------------------------------- // // Function: QueryMappedCredAttributesCallback // // Synopsis: Queries the application mapper for the specified property. // // Arguments: [hLocator] -- Handle to locator. // [dwAttribute] -- Attribute to query. // [pInput] -- HMAPPER structure. // [pOutput] -- Pointer to attribute data (in the // application's address space). // // History: 03-16-98 jbanes Created // // Notes: // //---------------------------------------------------------------------------- SECURITY_STATUS QueryMappedCredAttributesCallback( ULONG_PTR Mapper, ULONG_PTR hLocator, SecBuffer *pInput, SecBuffer *pOutput) { HMAPPER * phMapper; DWORD dwAttribute; PVOID pvBuffer; DWORD cbBuffer; DWORD Status; if(!SchannelInit(TRUE)) { return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR); } DebugLog((DEB_TRACE, "QueryMappedCredAttributesCallback\n")); phMapper = (HMAPPER *)Mapper; // Parse input buffer SP_ASSERT(pInput->cbBuffer == sizeof(DWORD)); dwAttribute = *(DWORD *)pInput->pvBuffer; // Query propery. try { // Determine buffer size. Status = phMapper->m_vtable->QueryMappedCredentialAttributes( phMapper, hLocator, dwAttribute, NULL, &cbBuffer); if(FAILED(Status)) { return SP_LOG_RESULT(Status); } // Allocate memory. This gets freed by the APPLICATION with FreeSecurityBuffer() call // SPExternalAlloc() for the above reason!!!! pvBuffer = SPExternalAlloc(cbBuffer); if(pvBuffer == NULL) { return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); } // Read propery. Status = phMapper->m_vtable->QueryMappedCredentialAttributes( phMapper, hLocator, dwAttribute, pvBuffer, &cbBuffer); if(FAILED(Status)) { SPExternalFree(pvBuffer); return SP_LOG_RESULT(Status); } } except(EXCEPTION_EXECUTE_HANDLER) { return SP_LOG_RESULT(SEC_E_INVALID_HANDLE); } // Build output buffer pOutput->BufferType = SECBUFFER_DATA; pOutput->cbBuffer = sizeof(PVOID); pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer); if(pOutput->pvBuffer == NULL) { SPExternalFree(pvBuffer); return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); } *(PVOID *)(pOutput->pvBuffer) = pvBuffer; return SEC_E_OK; }