windows-nt/Source/XPSP1/NT/mergedcomponents/advapi32/efs.c

1009 lines
19 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
efs.c
Abstract:
EFS (Encrypting File System) API Interfaces
Author:
Robert Reichel (RobertRe)
Robert Gu (RobertG)
Environment:
Revision History:
--*/
#undef WIN32_LEAN_AND_MEAN
#include "advapi.h"
#include <windows.h>
#include <feclient.h>
#define FE_CLIENT_DLL L"feclient.dll"
//
// Global Variables
//
LPFE_CLIENT_INFO FeClientInfo = NULL;
HMODULE FeClientModule = NULL;
CRITICAL_SECTION FeClientLoadCritical;
LPWSTR
GetFeClientDll(
VOID
)
/*++
Routine Description:
This routine obtains the name of the currently installed client
encryption dll (which is currently hardcoded).
Arguments:
None.
Return Value:
Returns the name of the current DLL, or NULL on error.
--*/
{
return( FE_CLIENT_DLL );
}
BOOL
LoadAndInitFeClient(
VOID
)
/*++
Routine Description:
This routine finds the name of the proper client dll (by some as of
yet unspecified means) and proceeds to load it and initialize it.
Arguments:
None.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more error information.
--*/
{
LPWSTR FeClientDllName;
LPFEAPI_CLIENT_INITIALIZE ClientInitRoutine;
BOOL Inited;
//
// GetFeClientDll returns a hard coded name.
// If we get this name dynamically later, we will
// need to free FeClientDllName.
//
FeClientDllName = GetFeClientDll();
EnterCriticalSection(&FeClientLoadCritical);
if (FeClientInfo) {
LeaveCriticalSection(&FeClientLoadCritical);
return( TRUE );
}
if (FeClientDllName) {
FeClientModule = LoadLibraryW( FeClientDllName );
if (FeClientModule == NULL) {
DbgPrint("Unable to load client dll, error = %d\n",GetLastError());
LeaveCriticalSection(&FeClientLoadCritical);
return( FALSE );
}
}
ClientInitRoutine = (LPFEAPI_CLIENT_INITIALIZE) GetProcAddress( FeClientModule, (LPCSTR)"FeClientInitialize");
if (NULL == ClientInitRoutine) {
FreeLibrary( FeClientModule );
DbgPrint("Unable to locate init routine, error = %d\n",GetLastError());
LeaveCriticalSection(&FeClientLoadCritical);
return( FALSE );
}
Inited = (*ClientInitRoutine)( FE_REVISION_1_0, &FeClientInfo );
LeaveCriticalSection(&FeClientLoadCritical);
if (!Inited) {
FreeLibrary( FeClientModule );
return( FALSE );
}
return( TRUE );
}
BOOL
WINAPI
EncryptFileA (
LPCSTR lpFileName
)
/*++
Routine Description:
ANSI Stub to EncryptFileW
Arguments:
lpFileName - The name of the file to be encrypted.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more information.
--*/
{
UNICODE_STRING Unicode;
WCHAR UnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
ANSI_STRING AnsiString;
NTSTATUS Status;
Unicode.Length = 0;
Unicode.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof( WCHAR );
Unicode.Buffer = UnicodeBuffer;
RtlInitAnsiString(&AnsiString,lpFileName);
Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
if ( !NT_SUCCESS(Status) ) {
if ( Status == STATUS_BUFFER_OVERFLOW ) {
SetLastError(ERROR_FILENAME_EXCED_RANGE);
} else {
BaseSetLastNTError(Status);
}
return FALSE;
}
return ( EncryptFileW( Unicode.Buffer ));
}
BOOL
WINAPI
EncryptFileW (
LPCWSTR lpFileName
)
/*++
Routine Description:
Win32 EncryptFile API
Arguments:
lpFileName - Supplies the name of the file to be encrypted.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more information.
--*/
{
BOOL rc;
DWORD Result;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
Result = FeClientInfo->lpServices->EncryptFile( lpFileName );
if (ERROR_SUCCESS != Result) {
SetLastError( Result );
return( FALSE );
}
return( TRUE );
}
BOOL
WINAPI
DecryptFileA (
IN LPCSTR lpFileName,
IN DWORD dwRecovery
)
/*++
Routine Description:
ANSI Stub for the DecryptFileW API
Arguments:
lpFileName - Supplies the name of the file to be decrypted.
dwRecover - Supplies whether this is a recovery operation or a
normal decryption operation.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more information.
--*/
{
UNICODE_STRING Unicode;
WCHAR UnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
ANSI_STRING AnsiString;
NTSTATUS Status;
Unicode.Length = 0;
Unicode.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof( WCHAR );
Unicode.Buffer = UnicodeBuffer;
RtlInitAnsiString(&AnsiString,lpFileName);
Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
if ( !NT_SUCCESS(Status) ) {
if ( Status == STATUS_BUFFER_OVERFLOW ) {
SetLastError(ERROR_FILENAME_EXCED_RANGE);
} else {
BaseSetLastNTError(Status);
}
return FALSE;
}
return ( DecryptFileW( Unicode.Buffer, dwRecovery ));
}
BOOL
WINAPI
DecryptFileW (
IN LPCWSTR lpFileName,
IN DWORD dwRecovery
)
/*++
Routine Description:
Win32 DecryptFile API
Arguments:
lpFileName - Supplies the name of the file to be encrypted.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more information.
--*/
{
BOOL rc;
DWORD Result;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
Result = FeClientInfo->lpServices->DecryptFile( lpFileName, dwRecovery );
if (ERROR_SUCCESS != Result) {
SetLastError( Result );
return( FALSE );
}
return( TRUE );
}
BOOL
WINAPI
FileEncryptionStatusA (
LPCSTR lpFileName,
LPDWORD lpStatus
)
/*++
Routine Description:
ANSI Stub to FileEncryptionStatusW
Arguments:
lpFileName - The name of the file to be checked.
lpStatus - The status of the file.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError() for more information.
--*/
{
ANSI_STRING AnsiString;
NTSTATUS Status;
UNICODE_STRING Unicode;
WCHAR UnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
Unicode.Length = 0;
Unicode.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof( WCHAR );
Unicode.Buffer = UnicodeBuffer;
RtlInitAnsiString(&AnsiString,lpFileName);
Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
if ( !NT_SUCCESS(Status) ) {
if ( Status == STATUS_BUFFER_OVERFLOW ) {
SetLastError(ERROR_FILENAME_EXCED_RANGE);
} else {
BaseSetLastNTError(Status);
}
return FALSE;
}
return ( FileEncryptionStatusW( Unicode.Buffer, lpStatus ));
}
BOOL
WINAPI
FileEncryptionStatusW (
LPCWSTR lpFileName,
LPDWORD lpStatus
)
/*++
Routine Description:
Win32 FileEncryptionStatus API
Arguments:
lpFileName - Supplies the name of the file to be encrypted.
lpStatus - The status of the file.
Return Value:
TRUE on success, FALSE on failure. Callers may call GetLastError()
for more information.
--*/
{
BOOL rc;
DWORD Result;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
return (FeClientInfo->lpServices->FileEncryptionStatus( lpFileName, lpStatus ));
}
DWORD
WINAPI
OpenEncryptedFileRawA(
LPCSTR lpFileName,
ULONG Flags,
PVOID * Context
)
{
ANSI_STRING AnsiString;
NTSTATUS Status;
UNICODE_STRING Unicode;
WCHAR UnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
Unicode.Length = 0;
Unicode.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof( WCHAR );
Unicode.Buffer = UnicodeBuffer;
RtlInitAnsiString(&AnsiString,lpFileName);
Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
if ( !NT_SUCCESS(Status) ) {
if ( Status == STATUS_BUFFER_OVERFLOW ) {
SetLastError(ERROR_FILENAME_EXCED_RANGE);
} else {
BaseSetLastNTError(Status);
}
return FALSE;
}
return ( OpenEncryptedFileRawW( Unicode.Buffer, Flags, Context ));
}
DWORD
WINAPI
OpenEncryptedFileRawW(
LPCWSTR lpFileName,
ULONG Flags,
PVOID * Context
)
{
BOOL rc;
DWORD Result;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(GetLastError());
}
}
return (FeClientInfo->lpServices->OpenFileRaw( lpFileName, Flags, Context ));
}
DWORD
WINAPI
ReadEncryptedFileRaw(
PFE_EXPORT_FUNC ExportCallback,
PVOID CallbackContext,
PVOID Context
)
{
//
// It doesn't make sense to call this before calling OpenRaw, so don't
// bother checking to see if the module is loaded or not. We'll fault
// in the user process if it isn't.
//
return (FeClientInfo->lpServices->ReadFileRaw( ExportCallback, CallbackContext, Context ));
}
DWORD
WINAPI
WriteEncryptedFileRaw(
PFE_IMPORT_FUNC ImportCallback,
PVOID CallbackContext,
PVOID Context
)
{
//
// It doesn't make sense to call this before calling OpenRaw, so don't
// bother checking to see if the module is loaded or not. We'll fault
// in the user process if it isn't.
//
return (FeClientInfo->lpServices->WriteFileRaw( ImportCallback, CallbackContext, Context ));
}
VOID
WINAPI
CloseEncryptedFileRaw(
PVOID Context
)
{
FeClientInfo->lpServices->CloseFileRaw( Context );
return;
}
DWORD
QueryUsersOnEncryptedFile(
IN LPCWSTR lpFileName,
OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pUsers
)
/*++
Routine Description:
Win32 interface for adding users to an encrypted file.
Arguments:
lpFileName - Supplies the name of the file to be modified.
pUsers - Returns a list of users on the file. This parameter
must be passed to FreeEncryptionCertificateHashList() when
no longer needed.
Return Value:
Win32 error.
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if ((lpFileName != NULL) && (pUsers != NULL)) {
return(FeClientInfo->lpServices->QueryUsers( lpFileName, pUsers ));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
VOID
FreeEncryptionCertificateHashList(
IN PENCRYPTION_CERTIFICATE_HASH_LIST pUsers
)
/*++
Routine Description:
Frees a certificate hash list as returned by QueryUsersOnEncryptedFile()
and QueryRecoveryAgentsOnEncryptedFile().
Arguments:
Supplies a list of users returned from QueryUsersOnEncryptedFile().
Return Value:
Win32 error.
--*/
{
//
// It is probably safe to assume that feclient.dll is loaded,
// since we wouldn't have one of these structures to free
// if it weren't.
//
if (pUsers != NULL) {
FeClientInfo->lpServices->FreeCertificateHashList( pUsers );
} else {
//
// nothing to do
//
}
return;
}
DWORD
QueryRecoveryAgentsOnEncryptedFile(
IN LPCWSTR lpFileName,
OUT PENCRYPTION_CERTIFICATE_HASH_LIST * pRecoveryAgents
)
/*++
Routine Description:
This routine returns a list of recovery agents on an encrypted
file.
Arguments:
lpFileName - Supplies the name of the file to be examined.
pRecoveryAgents - Returns a list of recovery agents, represented
by certificate hashes on the file. This list should be freed
by calling FreeEncryptionCertificateHashList().
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if ((lpFileName != NULL) && (pRecoveryAgents != NULL)) {
return(FeClientInfo->lpServices->QueryRecoveryAgents( lpFileName, pRecoveryAgents ));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
DWORD
RemoveUsersFromEncryptedFile(
IN LPCWSTR lpFileName,
IN PENCRYPTION_CERTIFICATE_HASH_LIST pHashes
)
/*++
Routine Description:
Takes a list of certificate hashes to be removed
from the passed file. Any that are found are removed,
the rest are ignored with no error return.
Arguments:
lpFileName - Supplies the name of the file to be modified.
pHashes - Supplies the list of hashes to be removed.
Return Value:
Win32 Error
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if ((lpFileName != NULL) && (pHashes != NULL)) {
return(FeClientInfo->lpServices->RemoveUsers( lpFileName, pHashes ));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
DWORD
AddUsersToEncryptedFile(
IN LPCWSTR lpFileName,
IN PENCRYPTION_CERTIFICATE_LIST pEncryptionCertificates
)
/*++
Routine Description:
This routine adds user keys to the passed encrypted file.
Arguments:
lpFileName - Supplies the name of the file to be encrypted.
pEncryptionCertificates - Supplies the list of certificates for
new users to be added to the file.
Return Value:
Win32 Error
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if ((lpFileName != NULL) && (pEncryptionCertificates != NULL)) {
return(FeClientInfo->lpServices->AddUsers( lpFileName, pEncryptionCertificates ));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
DWORD
SetUserFileEncryptionKey(
PENCRYPTION_CERTIFICATE pEncryptionCertificate
)
/*++
Routine Description:
This routine will set the user's current EFS key to the one
contained in the passed certificate. If no certificate is
passed, a new key will be generated automatically.
Arguments:
pEncryptionCertificate - Optionally supplies the certificate
containing the new public key.
Return Value:
Win32 error
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
return(FeClientInfo->lpServices->SetKey( pEncryptionCertificate ));
/*
if (pEncryptionCertificate != NULL) {
return(FeClientInfo->lpServices->SetKey( pEncryptionCertificate ));
} else {
return( ERROR_INVALID_PARAMETER );
}*/
}
DWORD
DuplicateEncryptionInfoFile(
IN LPCWSTR SrcFileName,
IN LPCWSTR DstFileName,
IN DWORD dwCreationDistribution,
IN DWORD dwAttributes,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
/*++
Routine Description:
This routine duplicates the encryption information from the source file to the
destination file. Destination file will be created if not existing.
The destination file is overwritten.
Arguments:
SrcFileName - Supplies the source of the encryption information.
DstFileName - Supplies the target file, exclusive open is required on this file.
dwCreationDistribution - Create options.
If dwCreationDistribution != CREATE_NEW, dwCreationDistribution = CREATE_ALWAYS
dwAttributes - File attributes.
lpSecurityAttributes - Security attributes.
Return Value:
Win32 error on failure.
--*/
{
DWORD rc;
if (FeClientModule == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if (SrcFileName && DstFileName) {
return(FeClientInfo->lpServices->DuplicateEncryptionInfo( SrcFileName,
DstFileName,
dwCreationDistribution,
dwAttributes,
lpSecurityAttributes
));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
BOOL
WINAPI
EncryptionDisable(
IN LPCWSTR DirPath,
IN BOOL Disable
)
/*++
Routine Description:
This routine disable and enable EFS in the directory DirPath.
Arguments:
DirPath - Directory path.
Disable - TRUE to disable
Return Value:
TRUE for SUCCESS
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
return(FeClientInfo->lpServices->DisableDir( DirPath, Disable ));
}
WINADVAPI
DWORD
WINAPI
EncryptedFileKeyInfo(
IN LPCWSTR lpFileName,
IN DWORD InfoClass,
OUT PEFS_RPC_BLOB * KeyInfo
)
/*++
Routine Description:
Win32 interface for adding users to an encrypted file.
Arguments:
lpFileName - Supplies the name of the file to be modified.
InfoClass - Information requested. Only support 1 for now.
KeyInfo - Returns Key info
Return Value:
Win32 error.
--*/
{
DWORD rc;
//
// See if the module has been loaded, and if not, load it into this
// process.
//
if (FeClientInfo == NULL) {
rc = LoadAndInitFeClient();
if (!rc) {
return(rc);
}
}
if ((lpFileName != NULL) && (KeyInfo != NULL)) {
return(FeClientInfo->lpServices->GetKeyInfo( lpFileName, InfoClass, KeyInfo ));
} else {
return( ERROR_INVALID_PARAMETER );
}
}
WINADVAPI
VOID
WINAPI
FreeEncryptedFileKeyInfo(
IN PEFS_RPC_BLOB pKeyInfo
)
/*++
Routine Description:
Frees a KeyInfo as returned by EncryptedFileKeyInfo();
Arguments:
pKeyInfo - Supplies a KeyInfo returned from EncryptedFileKeyInfo().
Return Value:
No.
--*/
{
//
// It is probably safe to assume that feclient.dll is loaded,
// since we wouldn't have one of these structures to free
// if it weren't.
//
if (pKeyInfo != NULL) {
FeClientInfo->lpServices->FreeKeyInfo( pKeyInfo );
} else {
//
// nothing to do
//
}
return;
}