The Windows File Management 11

 

 

 

 

 

Adding Users to an Encrypted File Program Example

 

The following code sample adds a new user to an existing encrypted file by using the AddUsersToEncryptedFile() function. It requires the user's EFS certificate (from the Active Directory) to exist in the Trusted People user certificate store. This sample adds a new Data Recovery Field to the encrypted file. As a result, the newly added user can decrypt the encrypted file. The caller must already have access to the encrypted file, either as the original owner, the data recovery agent, or as a user who was previously added to the encrypted file. This example is not supported in Windows 2000 because you cannot add multiple users to an encrypted file.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Adding Users to an Encrypted File Program Example: Creating new Win32 C++ console application project in Visual C++ .NET

 

Then, add the source file and give it a suitable name.

 

Adding Users to an Encrypted File Program Example: Adding new C++ source file for C++ source code to the existing C++ project

 

Next, add the following source code.

 

// Adds a user to an encrypted file example

#include <Windows.h>

#include <malloc.h>

#include <stdio.h>

#include <wincrypt.h>

#include <winefs.h>

// A safer version for string manipulation

#include <strsafe.h>

 

// Link with the following libraries

#pragma comment(lib, "Advapi32.lib")

#pragma comment(lib, "Crypt32.lib")

 

// A prototype that receives a function name, displaying

// system error code and its respective message

void DisplayErrorBox(LPTSTR lpszFunction);

 

// Utility function that outputs this application's usage instructions.

void Usage(LPWSTR wszAppName)

{

    wprintf(L"\n%s: Adds users to encrypted files.\n", wszAppName);

    wprintf(L"Usage:\t%s <file> <username> <subjectname>\n\n", wszAppName);

    wprintf(L"\t<file> is the name of the file\n");

    wprintf(L"\t<username> is the name of the user's account\n");

    wprintf(L"\t\tExample: for name@example.com, use \"name\"\n");

    wprintf(L"\t<subjectname> is the \"IssuedTo\" name on the ");

    wprintf(L"certificate\n\t\tfrom the TrustedPeople store.\n");

    exit(1);

}

 

//  void ErrorExit(LPWSTR wszErrorMessage, DWORD dwErrorCode);

void wmain(int argc, WCHAR *argv[])

{

    LPWSTR wszFile    = NULL;

    LPWSTR wszAccount = NULL;

    LPWSTR wszSubject = NULL;

    PSID   pSid       = NULL;

    DWORD  cbSid      = 0;

    LPWSTR wszDomain  = NULL;

    DWORD  cchDomain  = 0;

    SID_NAME_USE SidType = SidTypeUser;

    HCERTSTORE hStore = NULL;

    PCCERT_CONTEXT pCertContext = NULL;

    PENCRYPTION_CERTIFICATE      pEfsEncryptionCert     = NULL;

    PENCRYPTION_CERTIFICATE_LIST pEfsEncryptionCertList = NULL;

    DWORD dwResult = ERROR_SUCCESS;

 

    // Simple check whether to explain usage to the user.

    if(argc !=4)

    {

        Usage(argv[0]);

    }

 

    // TODO: Check the parameters for correctness.

    wszFile = argv[1];

    wszAccount = argv[2];

    wszSubject = argv[3];

 

    // First, look up the user's SID using the specified account name.

    // Call LookupAccountName twice; first to find the size of the

    // SID, and a second time to retrieve the SID.

    LookupAccountName(NULL,wszAccount,pSid,&cbSid, wszDomain, &cchDomain,&SidType);

    if(cbSid == 0)

    {

            DisplayErrorBox(L"LookupAccountName()");

            exit(1);

    }

      else

            wprintf(L"LookupAccountName() looks fine!\n");

 

    pSid = (PSID)malloc(cbSid);

 

    if(!pSid)

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

      else

            wprintf(L"SID allocated successfully!\n");

 

    wszDomain = (LPWSTR)malloc(cchDomain * sizeof(WCHAR));

 

    if(!wszDomain)

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

      else

            wprintf(L"malloc() for domain name looks fine!\n");

 

    if(!LookupAccountName(NULL,wszAccount,pSid,&cbSid, wszDomain,&cchDomain,&SidType))

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

      else

            wprintf(L"LookupAccountName() looks fine!\n");

 

    // Obtain the user's certificate.

    // Search the TrustedPeople store for the specified subject name.

    // Anyone who has encrypted a file on the computer has an

    // encryption certificate placed the TrustedPeople store by the

    // system. It is likely that the user has a matching private key.

    hStore = CertOpenSystemStore( (HCRYPTPROV)NULL,L"TrustedPeople");

    if (!hStore)

    {

            DisplayErrorBox(L"CertOpenSystemStore()");

    }

    else

            wprintf(L"CertOpenSystemStore() looks fine!\n");

 

    pCertContext = CertFindCertificateInStore(hStore,

                           X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,

                           0,

                           CERT_FIND_SUBJECT_STR,

                           (VOID*)wszSubject,

                           NULL);

    if(!pCertContext)

    {

            DisplayErrorBox(L"FindCertificateInStore()");

            exit(1);

    }

    else

            wprintf(L"FindCertificateInStore() looks fine!\n");

 

    // Create the ENCRYPTION_CERTIFICATE using the cert context and the user's SID.

    pEfsEncryptionCert = (PENCRYPTION_CERTIFICATE)malloc(sizeof(ENCRYPTION_CERTIFICATE));

 

    if(!pEfsEncryptionCert)

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

    else

            wprintf(L"malloc() for structure looks fine!\n");

 

    pEfsEncryptionCert->cbTotalLength = sizeof(ENCRYPTION_CERTIFICATE);

    pEfsEncryptionCert->pUserSid = (SID *)pSid;

    pEfsEncryptionCert->pCertBlob = (PEFS_CERTIFICATE_BLOB)malloc(sizeof(EFS_CERTIFICATE_BLOB));

 

    if(!pEfsEncryptionCert->pCertBlob)

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

    else

            wprintf(L"malloc() cert blob allocated!\n");

 

    pEfsEncryptionCert->pCertBlob->dwCertEncodingType = pCertContext->dwCertEncodingType;

    pEfsEncryptionCert->pCertBlob->cbData = pCertContext->cbCertEncoded;

    pEfsEncryptionCert->pCertBlob->pbData = pCertContext->pbCertEncoded;

 

    // AddUsersToEncryptedFile takes an ENCRYPTION_CERTIFICATE_LIST;

    // create one with only one ENCRYPTION_CERTIFICATE in it.

    pEfsEncryptionCertList = (PENCRYPTION_CERTIFICATE_LIST)malloc(sizeof(ENCRYPTION_CERTIFICATE_LIST));

 

    if(!pEfsEncryptionCertList)

    {

            DisplayErrorBox(L"malloc()");

            exit(1);

    }

    else

            wprintf(L"malloc() - structure allocation looks fine!\n");

 

    pEfsEncryptionCertList->nUsers = 1;

    pEfsEncryptionCertList->pUsers = &pEfsEncryptionCert;

 

    // Call the API to add the user.

    // Adds user keys to the specified encrypted file.

    dwResult = AddUsersToEncryptedFile(wszFile,pEfsEncryptionCertList);

    if(dwResult == ERROR_SUCCESS)

    {

        wprintf(L"The user was successfully added to the file.\n");

    }

    else

    {

            DisplayErrorBox(L"AddUsersToEncryptedFile()");

    }

 

    // Clean up all allocated resources

      if(pSid)

      {

            wprintf(L"Freeing up the SID...\n");

            free(pSid);

      }

 

    if(wszDomain)

      {

            wprintf(L"Freeing up the domain name...\n");

            free(wszDomain);

      }

 

    if(pCertContext)

      {

            wprintf(L"Freeing up the CertFreeCertificateContext...\n");

            CertFreeCertificateContext(pCertContext);

      }

 

    if(hStore)

      {

            wprintf(L"Closing the cert store...\n");

            CertCloseStore(hStore,CERT_CLOSE_STORE_FORCE_FLAG);

      }

 

      wprintf(L"Freeing up other allocated resources...\n");

 

    if(pEfsEncryptionCertList)

    {

            // Just free up the allocated storage pUsers[0]

            //if (pEfsEncryptionCertList->pUsers)

            //   {

            if(pEfsEncryptionCertList->pUsers[0])

            {

                  if((pEfsEncryptionCertList->pUsers[0])->pCertBlob)

                        free((pEfsEncryptionCertList->pUsers[0])->pCertBlob);

                  free(pEfsEncryptionCertList->pUsers[0]);

            }

            //     free(pEfsEncryptionCertList->pUsers);

            //  }

        free(pEfsEncryptionCertList);

    }

 

    wprintf(L"The program ran to completion without error.\n");

    exit(0);

}

 

void DisplayErrorBox(LPTSTR lpszFunction)

{

    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;

    LPVOID lpDisplayBuf;

    DWORD dw = GetLastError();

 

    FormatMessage(

        FORMAT_MESSAGE_ALLOCATE_BUFFER |

        FORMAT_MESSAGE_FROM_SYSTEM |

        FORMAT_MESSAGE_IGNORE_INSERTS,

        NULL,

        dw,

        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

        (LPTSTR) &lpMsgBuf,

        0, NULL );

 

    // Display the error message and clean up

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(WCHAR));

    StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(WCHAR),  L"%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);

    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, L"Error", MB_OK);

 

    LocalFree(lpMsgBuf);

    LocalFree(lpDisplayBuf);

}

 

To test this program, it is better to run it in a domain based, active directory environment. In the following test, we just run it on standalone Windows XP Pro.

Firstly, we create a word file, testfilencrypt.doc.

 

Adding Users to an Encrypted File Program Example: Creating a file for testing

 

Next, we invoke the file's property page. Click the Advanced button.

 

Adding Users to an Encrypted File Program Example: Invoking the file property's page

 

Tick the Encrypt contents to secure data tick box and click OK.

 

Adding Users to an Encrypted File Program Example: Encrypting a file

 

Then click the OK button.

 

Adding Users to an Encrypted File Program Example: Encrypted file's size

 

Select Encrypt the file only and click OK.

 

Adding Users to an Encrypted File Program Example: In the real application, the folder also must be encrypted

 

 Then click the Advanced button again.

 

Adding Users to an Encrypted File Program Example: The file should be encrypted already

 

Click the Details button.

 

Adding Users to an Encrypted File Program Example: Viewing the encrypted file properties

 

The certificate for user mike spoon (in this case, the logged user) will be created using local certificate store. Manually we can add other user, click the Add button.

 

Adding Users to an Encrypted File Program Example: Adding user certificate

 

In this case we have another user which having a valid local store certificate.

 

Adding Users to an Encrypted File Program Example: Sharing the encrypted file with other users

 

Just click the Cancel button but for the following screenshot, click OK button.

 

Adding Users to an Encrypted File Program Example: Dismissing the encrypted file property page

 

In Windows, the encrypted file is shown in green colour.

 

Adding Users to an Encrypted File Program Example: The encrypted file shown in green colour

 

Next, run the program.

 

Adding Users to an Encrypted File Program Example: Running the program example without any argument

 

We are adding a user Johnny (also has a local certificate) to testfilencrypt.doc which owned by mike spoon.

 

Adding Users to an Encrypted File Program Example: Adding new user (with certificate) to the encrypted file

 

Finally, let verify the task. The user seems was added successfully and it is bad if the purpose is misused!

 

Adding Users to an Encrypted File Program Example: Well, the new user was added successfully!

 

 

 

 

< Windows Files 10 | Win32 Programming | Win32 File Index | Windows Files 12 >